package com.ssy.lingxi.contract.serviceimpl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONUtil;
import com.ssy.lingxi.after.sale.api.feign.ReturnGoodsControllerFeign;
import com.ssy.lingxi.after.sale.api.model.vo.request.ReturnListGoodsDetailVO;
import com.ssy.lingxi.after.sale.api.model.vo.response.ReturnGoodsDetailListResponse;
import com.ssy.lingxi.after.sale.api.model.vo.response.ReturnGoodsInfoVO;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.component.rabbitMQ.service.IRabbitMQUtils;
import com.ssy.lingxi.contract.api.model.constant.ContractOrderTypeEnum;
import com.ssy.lingxi.contract.api.model.vo.request.ContractOrderListRequest;
import com.ssy.lingxi.contract.entity.ApplyAmountOrderDO;
import com.ssy.lingxi.contract.entity.ContractDO;
import com.ssy.lingxi.contract.model.vo.common.response.ContractOrderPageResponse;
import com.ssy.lingxi.contract.service.IFeignService;
import com.ssy.lingxi.contract.utils.FeignLogUtils;
import com.ssy.lingxi.dto.request.*;
import com.ssy.lingxi.dto.response.*;
import com.ssy.lingxi.feign.ApplyAmountControllerFeign;
import com.ssy.lingxi.feign.CorporateAccountConfigControllerFeign;
import com.ssy.lingxi.feign.InvoiceMessageControllerFeigen;
import com.ssy.lingxi.feign.MemberSettlementControllerFeign;
import com.ssy.lingxi.message.api.feign.SystemMessageControllerFeign;
import com.ssy.lingxi.message.api.vo.request.SystemMessageRequest;
import com.ssy.lingxi.order.api.feign.OrderFeignService;
import com.ssy.lingxi.order.api.model.vo.request.OrderContractFeignVO;
import com.ssy.lingxi.order.api.model.vo.request.OrderIdsFeignVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderAfterSaleOrderContractFeignVO;
import com.ssy.lingxi.order.api.model.vo.response.OrderAfterSaleStatusVO;
import com.ssy.lingxi.product.api.feign.ICommodityFeign;
import com.ssy.lingxi.product.api.model.request.feign.CommodityPriceRequest;
import com.ssy.lingxi.product.api.model.response.feign.CommoditySkuStockResponse;
import com.ssy.lingxi.report.api.constant.ReportConstants;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeAddVO;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 内部接口实现
 *
 * @author 伍将
 * @version 2.0.0
 * @date 2021/3/1
 */
@Slf4j
@Service
public class FeignServiceImpl implements IFeignService {
    @Resource
    private MemberSettlementControllerFeign settlementControllerFeign;

    @Resource
    private InvoiceMessageControllerFeigen invoiceMessageControllerFeigen;

    @Resource
    private ReturnGoodsControllerFeign returnGoodsControllerFeign;

    @Resource
    private CorporateAccountConfigControllerFeign corporateAccountConfigControllerFeign;

    @Resource
    private SystemMessageControllerFeign systemMessageControllerFeign;
    @Resource
    IRabbitMQUtils rabbitMQUtils;
    @Resource
    private ICommodityFeign commodityFeign;
    @Resource
    private OrderFeignService orderFeignService;

    @Resource
    private ApplyAmountControllerFeign applyAmountControllerFeign;


    /**
     * 获取最后一步
     *
     * @param steps 步骤列表
     * @return 最后一步
     */
    private Integer getLastStep(List<Integer> steps) {
        Integer result = 0;
        if (null != steps && steps.size() > 0) {
            Integer outerLastStep = steps.get(steps.size() - 1);
            // 最后一步为0时，代表已完成，则取上一步骤值
            if (result.equals(outerLastStep)) {
                if (steps.size() > 1) {
                    result = steps.get(steps.size() - 2);
                }
            } else {
                result = outerLastStep;
            }
        }

        return result;
    }

    /**
     * 更新合同来源
     *
     * @param contractDO: 合同
     * @param isRecovery: 是否还原：false-否，true-是
     * @return 操作结果
     * @author 伍将
     * @date 2021/3/3
     **/
    @Override
    public Wrapper<Void> updateContractSource(ContractDO contractDO, Boolean isRecovery) {

        // 如果来源id有值，则需要更新合同来源信息
        if (null != contractDO.getSourceId() && contractDO.getSourceId() > 0) {

            // todo 根据寻源类与isRecovery值调用内部接口更新数据来源状态
        }

        return Wrapper.success();
    }

    /**
     * 新增结算请款单
     *
     * @param entity:     请款单
     * @param totalCount: 总单数
     * @return 操作结果
     * @author 伍将
     * @date 2021/3/24
     **/
    @Override
    public Wrapper<Void> addSettlementApplyAmount(ApplyAmountOrderDO entity, Long totalCount) {

        AddSettlementApplyAmountVO addVO = new AddSettlementApplyAmountVO();
        // 根据请款金额调整付款预收款人
        if (entity.getApplyAmount() > 0) {
            addVO.setMemberId(entity.getPayeeMemberId());
            addVO.setRoleId(entity.getPayeeRoleId());
            addVO.setSettlementName(entity.getPayeeName());
            addVO.setPayMemberId(entity.getMemberId());
            addVO.setPayRoleId(entity.getRoleId());
            addVO.setPayName(entity.getMemberName());
        } else {
            addVO.setMemberId(entity.getMemberId());
            addVO.setRoleId(entity.getRoleId());
            addVO.setSettlementName(entity.getMemberName());
            addVO.setPayMemberId(entity.getPayeeMemberId());
            addVO.setPayRoleId(entity.getPayeeRoleId());
            addVO.setPayName(entity.getPayeeName());
        }
        addVO.setSettlementWay(entity.getPayWay());
        addVO.setTotalCount(totalCount);
        addVO.setAmount(entity.getApplyAmount());
        addVO.setPrePayTime(entity.getExpectPayTime());
        addVO.setOrderId(entity.getId());
        addVO.setOrderNo(entity.getApplyNo());
        Wrapper<Void> wrapper = settlementControllerFeign.addApplyAmount(addVO);
        if (null == wrapper || ResponseCode.SUCCESS.getCode() != wrapper.getCode()) {
            log.warn("addSettlementApplyAmount request:{} response:{}", JSONUtil.toJsonStr(addVO), JSONUtil.toJsonStr(wrapper));
        }
        return Wrapper.success();
    }

    /**
     * 根据退货订单ids,查询退货订单信息（状态）列表
     *
     * @param orderIds: 订单ids
     * @return 查询退货订单信息（状态）列表
     */
    @Override
    public List<ReturnGoodsInfoVO> getReturnGoodsInfoListByIds(List<Long> orderIds) {
        Wrapper<List<ReturnGoodsInfoVO>> orderInfoListByIds = returnGoodsControllerFeign.getOrderInfoListByIds(orderIds);
        FeignLogUtils.printLog("查询退货订单状态",orderInfoListByIds,orderIds);
        if (null == orderInfoListByIds || ResponseCode.SUCCESS.getCode() != orderInfoListByIds.getCode()
                || null == orderInfoListByIds.getData()) {
            throw new BusinessException(ResponseCode.CONTRACT_APPLY_AMOUNT_ORDER_TO_ORDER_NOT_EXISTS);
        }
        return orderInfoListByIds.getData();
    }

    /**
     * 根据单据编号+结算类型，获取单据[发票凭证]信息列表
     *
     * @param invoiceProveGetVO 单据编号+结算类型
     * @return 单据[发票凭证]信息列表
     */
    @Override
    public List<InvoiceProveVO> getInvoiceProve(InvoiceProveGetVO invoiceProveGetVO) {
        Wrapper<List<InvoiceProveVO>> invoiceProve = invoiceMessageControllerFeigen.getInvoiceProve(invoiceProveGetVO);
        if (null == invoiceProve || ResponseCode.SUCCESS.getCode() != invoiceProve.getCode()
                || null == invoiceProve.getData()) {
            throw new BusinessException(ResponseCode.CONTRACT_APPLY_AMOUNT_ORDER_TO_ORDER_NOT_EXISTS);
        }
        return invoiceProve.getData();
    }

    /**
     * 查询会员对公账户
     *
     * @param memberId 会员id
     * @param memberRoleId 会员角色id
     * @return 会员对公账户
     */
    @Override
    public Wrapper<CorporateAccountConfigResponse> getCorporateAccountConfig(Long memberId, Long memberRoleId) {
        Wrapper<CorporateAccountConfigResponse> corporateAccountConfigResponseWrapper = corporateAccountConfigControllerFeign.corporateAccountConfig(memberId, memberRoleId);
        FeignLogUtils.printLogForPrimitiveTypes("查询会员对公账户",corporateAccountConfigResponseWrapper,memberId,memberRoleId);
        return corporateAccountConfigResponseWrapper;
    }

    @Override
    public List<OrderAfterSaleStatusVO> getOrderStateList(List<Long> orderIds) {
        OrderIdsFeignVO request = new OrderIdsFeignVO();
        request.setOrderIds(orderIds);
        Wrapper<List<OrderAfterSaleStatusVO>> orderWrapper = orderFeignService.findAfterSaleOrderStatuses(request);
        FeignLogUtils.printLog("查询订单",orderWrapper,request);
        if (null == orderWrapper || ResponseCode.SUCCESS.getCode() != orderWrapper.getCode()
        ) {
            throw new BusinessException(ResponseCode.CONTRACT_APPLY_AMOUNT_ORDER_TO_ORDER_NOT_EXISTS);
        }
        return orderWrapper.getData();
    }

    /**
     * 查询合同下的退款单--售后服务
     *
     * @param request 查询请求
     * @return 合同下的退款单
     */
    @Override
    public List<ReturnGoodsDetailListResponse> getContractRefundOrderList(ReturnListGoodsDetailVO request) {
        Wrapper<List<ReturnGoodsDetailListResponse>> orderWrapper = returnGoodsControllerFeign.getOrderListByContractId(request);
        if (null == orderWrapper || ResponseCode.SUCCESS.getCode() != orderWrapper.getCode()
        ) {
            return null;
        }
        return orderWrapper.getData();
    }

    @Override
    public List<OrderAfterSaleOrderContractFeignVO> getContractOrderList(OrderContractFeignVO request) {
        Wrapper<List<OrderAfterSaleOrderContractFeignVO>> orderWrapper = orderFeignService.findAfterSaleOrderContracts(request);
        FeignLogUtils.printLog("getContractOrderList", orderWrapper,request);
        return orderWrapper.getData();
    }

    private List<ContractOrderPageResponse> convertContractOrderPageResponse(List<OrderAfterSaleOrderContractFeignVO> conOrderList) {
        return conOrderList.stream().map(o -> {
            ContractOrderPageResponse response = new ContractOrderPageResponse();
            response.setOrderAmount(o.getTotalAmount().doubleValue());
            response.setOrderId(o.getOrderId());
            response.setApplyNo(o.getOrderNo());
            response.setOrderTime(o.getCreateTime());
            response.setOuterStatus(o.getOuterStatus());
            response.setOuterStatusName(o.getOuterStatusName());
            response.setApplyAbstract(o.getDigest());
            response.setOrderTypeName(ContractOrderTypeEnum.ORDER.getMessage());
            response.setOrderType(ContractOrderTypeEnum.ORDER.getCode());
            response.setToBePayAmount(o.getTotalAmount().doubleValue());//待请款
            response.setIsHasTax(o.getTax()?1:0);
            response.setTaxRate(o.getTaxRate() == null ? 0D : o.getTaxRate().doubleValue());
            return response;
        }).collect(Collectors.toList());
    }

    public List<ContractOrderPageResponse> getContractOrderAndReturnList(UserLoginCacheDTO sysUser, ContractOrderListRequest request) {
        List<ContractOrderPageResponse> pageData = new ArrayList<>();
        //1.查询合同下的订单
        OrderContractFeignVO orderReq=new OrderContractFeignVO();
        orderReq.setOrderNo(request.getApplyNo());
        orderReq.setContractId(request.getContractId());
        orderReq.setDigest(request.getApplyAbstract());
        orderReq.setStartTime(request.getStartTime());
        orderReq.setEndTime(request.getEndTime());
        List<OrderAfterSaleOrderContractFeignVO> conOrderList = getContractOrderList(orderReq);
        if (CollectionUtil.isNotEmpty(conOrderList)) {
            List<ContractOrderPageResponse> orderList = convertContractOrderPageResponse(conOrderList);
            pageData.addAll(orderList);
        }
        //2.查询合同下的退款单
        ReturnListGoodsDetailVO vo = new ReturnListGoodsDetailVO();
        BeanUtils.copyProperties(request, vo);
        List<ReturnGoodsDetailListResponse> conRefundOrderList = getContractRefundOrderList(vo);
        if (CollectionUtil.isNotEmpty(conRefundOrderList)) {
            List<ContractOrderPageResponse> returnOrderList = conRefundOrderList.stream().map(o -> {
                ContractOrderPageResponse response = new ContractOrderPageResponse();
                BeanUtils.copyProperties(o, response);
                response.setOrderType(ContractOrderTypeEnum.RETURN_GOODS.getCode());
                response.setOrderTypeName(ContractOrderTypeEnum.RETURN_GOODS.getMessage());
                response.setOrderAmount(-o.getOrderAmount());
                response.setToBePayAmount(-o.getOrderAmount());
                response.setTaxRate(o.getTaxRate() == null ? 0 : o.getTaxRate());
                return response;
            }).collect(Collectors.toList());
            pageData.addAll(returnOrderList);
        }
        return pageData;
    }

    /**
     * 发送系统通知
     *
     * @param request:请求参数
     * @author 伍将
     * @date 2020/12/21
     **/
    @Async
    @Override
    public void sendSystemMessage(SystemMessageRequest request) {
        Wrapper<Void> wrapper = systemMessageControllerFeign.sendSystemMessage(request);
        FeignLogUtils.printLog("调用报表服务新增系统通知接口", wrapper, request);
    }

    @Async
    @Override
    public void batchSendSystemMessage(List<SystemMessageRequest> request) {
        Wrapper<Void> wrapper = systemMessageControllerFeign.batchSendSystemMessage(request);
        FeignLogUtils.printLog("调用报表服务批量新增系统通知接口", wrapper);
    }

    private void addSysOperateNoticeToMQ(OperateNoticeVO noticeVO, List<OperateNoticeVO> noticeVOs) {
        OperateNoticeAddVO addVO = new OperateNoticeAddVO();
        addVO.setOperateNoticeVO(noticeVO);
        addVO.setOperateNoticeVOList(noticeVOs);
        rabbitMQUtils.sendMsg(ReportConstants.REPORT_SYS_OPERATE_NOTICE_EXCHANGE, ReportConstants.REPORT_SYS_OPERATE_NOTICE_ROUTINGKEY, JSONUtil.toJsonStr(addVO));
    }

    @Override
    public void addSysOperateNoticeToMQ(OperateNoticeVO noticeVO) {
        addSysOperateNoticeToMQ(noticeVO, null);
    }

    @Override
    public void addSysOperateNoticeToMQ(List<OperateNoticeVO> noticeVOs) {
        addSysOperateNoticeToMQ(null, noticeVOs);
    }

    @Override
    public Wrapper<List<CommoditySkuStockResponse>> getCommoditySkuStock(CommodityPriceRequest request) {
        Wrapper<List<CommoditySkuStockResponse>> commoditySkuStock = commodityFeign.getCommoditySkuStock(request);
        FeignLogUtils.printLog("getCommoditySkuStock", commoditySkuStock, request);
        return commoditySkuStock;
    }

    @Override
    public Wrapper<PageData<ApplyAmountDetailSunVO>> pageContractExecuteDetail(ApplyAmountDetailSunQueryVO request) {
        Wrapper<PageData<ApplyAmountDetailSunVO>> wrapper = applyAmountControllerFeign.pageContractExecuteDetail(request);
        FeignLogUtils.printLog("pageContractExecuteDetail", wrapper, request);
        return wrapper;
    }

    @Override
    public Wrapper<List<ApplyAmountDetailTotalSunVO>> pageContractExecuteDetailSum(ApplyAmountDetailTotalSunQueryVO request) {
        Wrapper<List<ApplyAmountDetailTotalSunVO>> wrapper = applyAmountControllerFeign.pageContractExecuteDetailSum(request);
        FeignLogUtils.printLog("pageContractExecuteDetailSum", wrapper, request);
        return wrapper;
    }

    @Override
    public Wrapper<PageData<ApplyAmountSunVO>> pageListForSummary(ApplyAmountSunQueryVO request) {
        Wrapper<PageData<ApplyAmountSunVO>> wrapper = applyAmountControllerFeign.pageListForSummaryByParty(request);
        FeignLogUtils.printLog("pageListForSummary", wrapper, request);
        return wrapper;
    }

    @Override
    public Wrapper<List<ApplyAmountSunVO>> listForPaySummaryByParty(ApplyAmountSunQueryVO request) {
        Wrapper<List<ApplyAmountSunVO>> wrapper = applyAmountControllerFeign.listForPaySummaryByParty(request);
        FeignLogUtils.printLog("listForPaySummaryByParty", wrapper, request);
        return wrapper;
    }
}
